package com.groupbuying.redpacket.service.impl;

import com.groupbuying.redpacket.bo.RedPacketListBO;
import com.groupbuying.redpacket.constants.RedPacketRuleEnumConstants;
import com.groupbuying.redpacket.constants.RedisConstans;
import com.groupbuying.redpacket.context.FilterContextHandler;
import com.groupbuying.redpacket.domain.RedPacketListDO;
import com.groupbuying.redpacket.dto.RedPacketInfoTransferDTO;
import com.groupbuying.redpacket.service.GetRedPacketService;
import com.groupbuying.redpacket.service.RedPacketInfoTransferService;
import com.groupbuying.redpacket.service.RedPacketListService;
import com.groupbuying.redpacket.utils.JSONUtils;
import com.groupbuying.redpacket.utils.RedisUtils;
import com.groupbuying.redpacket.utils.apiresult.ApiResult;
import com.groupbuying.redpacket.utils.apiresult.ApiResultCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;

/**
 * @Author Vincentxin
 * @Date 2019/11/19
 */
@Service
public class GetRedPacketServiceImpl implements GetRedPacketService {
    private static final Logger logger = LoggerFactory.getLogger(GetRedPacketServiceImpl.class);
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private RedPacketListService redPacketListService;

    @Autowired
    private RedPacketInfoTransferService redPacketInfoTransferService;

    @Override
    public ApiResult getRedPacket() {

        //任务标示前缀
        String prefixRedisKey = RedisConstans.RED_PACKAGE_CONTROL;
        //任务ID
        Long taskId = (Long) FilterContextHandler.get("taskId");

        String userId = FilterContextHandler.getUserID();
        String phone = FilterContextHandler.getUsername();
        logger.info("用户ID:{},用户手机号:{},任务ID:{}", userId, phone, taskId);
        //如果不存在红包的key，则说明红包已经发完，或者活动还没有开始
        if (!redisUtils.isHasKey(prefixRedisKey + taskId)) {
            //没有中奖
            logger.info("红包已经发完了，用户:{}，未中奖！", userId);
            return ApiResult.failure(ApiResultCode.NOT_WINNING);
        }

        //剩余红包数量
        Long curRemainCount = redisUtils.sGetSetSize(prefixRedisKey + taskId);
        //剩余过期时间
        Long curRemainTime = redisUtils.getExpireMilliSeconds(prefixRedisKey);

        //按照最后10秒的时间不做限制判断
        if (curRemainTime > 3000L) {
            //如果红包总数和时间均值 大于 当前的实际均值 证明 现在红包发多了
            Long keepTime = (Long) FilterContextHandler.get("keepTime");
            Long redPacketsCounts = (Long) FilterContextHandler.get("redPacketsCounts");
            BigDecimal original = new BigDecimal(redPacketsCounts).divide(new BigDecimal(keepTime * 1000), 16, RoundingMode.HALF_DOWN);
            BigDecimal now = new BigDecimal(curRemainCount).divide(new BigDecimal(curRemainTime), 16, RoundingMode.HALF_DOWN);
            if (original.compareTo(now) == 1) {
                logger.info("用户:{}，因在中奖过过程中未满足时间分配次序，未中奖！", userId);
                return ApiResult.failure(ApiResultCode.NOT_WINNING);
            }
        }
        //从红包中随机取出一个红包
        RedPacketListBO redPacketBO = (RedPacketListBO) redisUtils.setPop(prefixRedisKey + taskId);
        logger.info("该用户抽中的红包是:{}", redPacketBO);

        //TODO 判断当前用户红包是否超限
        BigDecimal curActivityLimitAmount = (BigDecimal) FilterContextHandler.get("curActivityLimitAmount");
        //当前用户活动累计金额
        BigDecimal curActivityAmount = (BigDecimal) FilterContextHandler.get("curActivityAmount");
        //当前任务的限制金额
        BigDecimal curTaskLimitAmount = (BigDecimal) FilterContextHandler.get("curTaskLimitAmount");
        //当前用户任务的累计金额
        BigDecimal curTaskAmount = (BigDecimal) FilterContextHandler.get("curTaskAmount");
        //活动ID
        String activityId = (String) FilterContextHandler.get("activityId");
        logger.info("当前用户:{},电话:{},活动分类ID:{},任务Id:{},当前用户活动限制金额:{},当前用户活动累计金额:{},当前任务的限制金额:{},当前用户任务的累计金额:{},中奖红包:{}",
                userId, phone, activityId, taskId, curActivityLimitAmount, curActivityAmount, curTaskLimitAmount, curTaskAmount, redPacketBO);

        curTaskAmount = curTaskAmount.add(redPacketBO.getRedPacketAmount());
        curActivityAmount = curActivityAmount.add(redPacketBO.getRedPacketAmount());
        if (curTaskLimitAmount != null && (curTaskAmount.compareTo(curTaskLimitAmount) == 1 ||
                curActivityAmount.compareTo(curActivityLimitAmount) == 1) ){
            logger.info("用户累计金额超限制，用户:{}，未中奖！", userId);
            redisUtils.sSet(prefixRedisKey + taskId, redPacketBO);
            return ApiResult.failure(ApiResultCode.NOT_WINNING);
        }


        //TODO 判断用户是否已经抢过等级标示的红包
        boolean isLimitRedPacket = RedPacketRuleEnumConstants.ENUM_HAS_LEVEL.equals(redPacketBO.getRedPacketLevel());
        //用户抢到的是有等级的红包
        if (isLimitRedPacket) {
            //抢到限制红包的用户全部放到当前活动分类下的集合里面
            long userSetResult = redisUtils.sSet(prefixRedisKey +"DISTINCT_"+activityId, userId);
            //如果用户已经存在于限制集合中
            if (0L == userSetResult) {
                logger.info("用户:{},重复抢到了定额红包，不满足要求，红包{}", userId, redPacketBO);
                redisUtils.sSet(prefixRedisKey + taskId, redPacketBO);
                return ApiResult.failure(ApiResultCode.NOT_WINNING);
            }
        }


        //更新抢红包之后的数据库记录
        RedPacketListDO redPacketListDO = new RedPacketListDO();
        redPacketListDO.setId(Long.valueOf(redPacketBO.getId()));
        redPacketListDO.setUserId(userId);
        redPacketListDO.setPhone(phone);
        redPacketListDO.setWinningTime(new Date(System.currentTimeMillis()));
        try {
            redPacketListService.update(redPacketListDO);
        } catch (Exception e) {
            logger.error("抢红包后，更新红包失败：{},红包信息:{},错误原因：{}", redPacketListDO, redPacketBO,e.getMessage());
            if (isLimitRedPacket) {
                redisUtils.setRemove(prefixRedisKey +"DISTINCT_"+activityId, userId);
            }
            //重新将红包放入列表
            redisUtils.sSet(prefixRedisKey + taskId, redPacketBO);

            logger.error("未中奖！红包已经返回{}", redPacketListDO);
            return ApiResult.failure(ApiResultCode.NOT_WINNING);
        }
        //TODO 发送够样通知充值
        String activityName = FilterContextHandler.get("activityTaskName").toString()+"_第"+redPacketBO.getRound()+"轮";
        RedPacketInfoTransferDTO red = new RedPacketInfoTransferDTO(redPacketListDO, redPacketBO,activityName,FilterContextHandler.get("activityTaskName").toString(),redPacketBO.getRound().toString());
        boolean result = redPacketInfoTransferService.redPacketInfoTransferToMq(red);
        logger.info("发送够样");
        if (!result) {
            logger.error("=============抢红包后发送异步红包充值和通知失效：{}", redPacketListDO);
        }
        return ApiResult.success(ApiResultCode.WINNER, redPacketBO);
    }
}
